package com.blyat.xsoft.kernel.component.pool;

import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;

/**
 * @Auther: syh
 * @Date: 2020/8/3
 * @Description:
 */
public class ConnectionPoolSupport {

    public static <T extends Connection> GenericObjectPool<T> createGenericObjectPool(
            Supplier<T> connectionSupplier, GenericObjectPoolConfig<T> config) {
        // false 不启动动态代理
        return createGenericObjectPool(connectionSupplier, config, false);
    }

    public static <T extends Connection> GenericObjectPool<T> createGenericObjectPool(
            Supplier<T> connectionSupplier, GenericObjectPoolConfig<T> config, boolean wrapConnections) {
        if (Objects.isNull(connectionSupplier)) {
            throw new IllegalArgumentException("Connection supplier must not be null");
        }
        if (Objects.isNull(config)) {
            throw new IllegalArgumentException("GenericObjectPoolConfig must not be null");
        }

        AtomicReference<ObjectPool<T>> poolRef = new AtomicReference<>();

        GenericObjectPool<T> pool = new GenericObjectPool<T>(new ConnectionPooledObjectFactory<>(connectionSupplier), config) {
            @Override
            public T borrowObject() throws Exception {
                return wrapConnections ? ConnectionWrapping.wrapConnection(super.borrowObject(), poolRef.get()) : super.borrowObject();
            }

            @Override
            public void returnObject(T obj) {
                if (wrapConnections && obj instanceof ConnectionWrapping.HasTargetConnection) {
                    super.returnObject((T) ((ConnectionWrapping.HasTargetConnection) obj).getTargetConnection());
                    return;
                }
                super.returnObject(obj);
            }
        };

        poolRef.set(pool);
        return pool;
    }
}
